home *** CD-ROM | disk | FTP | other *** search
/ Programmer Power Tools / Programmer Power Tools.iso / tiff / packbits.c < prev    next >
Text File  |  1987-01-16  |  4KB  |  207 lines

  1. #define    MAXINBYTES    127
  2. #define    INITIAL        0
  3. #define    LITERAL        1
  4. #define    UNDECIDED    2
  5.  
  6. char CalcRaw ARGS((WORD, LPSTR, char *));
  7. LOCAL char CalcRaw (n, lpIn, rawrunbuf)
  8. WORD    n;
  9. LPSTR    lpIn;
  10. char    *rawrunbuf;
  11. {
  12.     char ncounts = 0;
  13.     char thisbyte;
  14.     char cnt = 1;
  15.     char runbyte = *lpIn++;
  16.  
  17.     while (--n) {
  18.         thisbyte = *lpIn++;
  19.         if (thisbyte == runbyte) {
  20.             cnt++;
  21.         } else { /* write prev raw run, & start a new one */
  22.             *rawrunbuf++ = cnt;
  23.             ncounts++;
  24.             cnt = 1;
  25.             runbyte = thisbyte;
  26.         }
  27.     }
  28.     *rawrunbuf = cnt;
  29.     return (++ncounts);
  30. }
  31.  
  32. /* this should be a Mac ToolBox lookalike
  33.  * n must be <= 127
  34.  */
  35. void PackBits ARGS((LPSTR *, LPSTR *, WORD));
  36. LOCAL void PackBits (plpIn, plpOut, n)
  37. LPSTR    *plpIn;
  38. LPSTR    *plpOut;
  39. WORD    n;
  40. {
  41.     LPSTR    lpIn = *plpIn;
  42.     LPSTR    lpOut = *plpOut;
  43.     char    runcount;
  44.     char    rawrunbuf[MAXINBYTES];
  45.     char    *pRaw;
  46.     char    nraw;
  47.     char    state;
  48.     char    rawcount;
  49.     char    twins;
  50.     RC        err = SUCCESS;
  51.  
  52.     if (n <= 0 || n > 127) {
  53.         DBMSG(("PackBits: n=%u\n", n));
  54.         err = IE_BUG;
  55.         goto cu0;
  56.     }
  57.  
  58.     /* calculate raw run counts
  59.      */
  60.     nraw = CalcRaw (n, lpIn, rawrunbuf);
  61.     if (nraw <= 0 || nraw > 127) {
  62.         DBMSG(("PackBits: nraw=%u\n",nraw));
  63.         err = IE_BUG;
  64.         goto cu0;
  65.     }
  66.  
  67.     /* initialize a few things
  68.      */
  69.     pRaw = rawrunbuf;
  70.     state = INITIAL;
  71.  
  72.     /* go through the raw run count array
  73.      */
  74.     while (nraw--) {
  75.  
  76.         rawcount = *pRaw++;
  77.  
  78.         if (rawcount < 1 || rawcount > 127) {
  79.             DBMSG(("PackBits: rawcount=%d\n",rawcount));
  80.             err = IE_BUG;
  81.             goto cu0;
  82.         }
  83.  
  84.         if (state == INITIAL) {
  85.             if (rawcount == 1) {
  86.                 state = LITERAL;
  87.                 runcount = 1;
  88.             } else if (rawcount == 2) {
  89.                 state = UNDECIDED;
  90.                 runcount = 2;
  91.             } else {    /* rawcount >= 3 */
  92.                 /* state = INITIAL; */
  93.                 /* write replicate run and update ptrs
  94.                  */
  95.                 *lpOut++ = -(rawcount - 1);
  96.                 *lpOut++ = *lpIn;
  97.                 lpIn += rawcount;
  98.             }
  99.  
  100.         } else if (state == LITERAL) {
  101.             if (rawcount < 3) {
  102.                 runcount += rawcount;
  103.             } else {
  104.                 state = INITIAL;
  105.                 /* write literal run and update ptrs
  106.                  */
  107.                 *lpOut++ = runcount - 1;
  108.                 if (runcount < 1 || runcount > 127) {
  109.                     DBMSG(("PackBits: runcount=%d\n",runcount));
  110.                     goto cu0;
  111.                 }
  112.                 lmemcpy (lpOut, lpIn, runcount);
  113.                 lpOut += runcount;
  114.                 lpIn += runcount;
  115.                 /* write replicate run and update ptrs
  116.                  */
  117.                 *lpOut++ = -(rawcount - 1);
  118.                 *lpOut++ = *lpIn;
  119.                 lpIn += rawcount;
  120.             }
  121.  
  122.         } else {    /* state = UNDECIDED */
  123.             if (rawcount == 1) {
  124.                 state = LITERAL;
  125.                 runcount++;
  126.             } else if (rawcount == 2) {
  127.                 /* state = UNDECIDED */
  128.                 runcount += 2;
  129.             } else {    /* rawcount >= 3 */
  130.                 state = INITIAL;
  131.                 if (runcount < 1 || runcount > 127) {
  132.                     DBMSG(("PackBits: runcount=%d\n",runcount));
  133.                     goto cu0;
  134.                 }
  135.                 /* write out runcount/2 twin replicate runs */
  136.                 for (twins = (runcount>>1); twins--; ) {
  137.                     *lpOut++ = -1;
  138.                     *lpOut++ = *lpIn;
  139.                     lpIn += 2;
  140.                 }
  141.                 /* write out this replicate run
  142.                  */
  143.                 *lpOut++ = -(rawcount - 1);
  144.                 *lpOut++ = *lpIn;
  145.                 lpIn += rawcount;
  146.             }
  147.         } /* end of UNDECIDED case */
  148.  
  149.     } /* end of main for loop */
  150.  
  151.     /* clean up hanging states
  152.      */
  153.     if (state == LITERAL) {
  154.         if (runcount < 1 || runcount > 127) {
  155.             DBMSG(("PackBits: runcount=%d\n",runcount));
  156.             goto cu0;
  157.         }
  158.         /* write out literal run
  159.          */
  160.         *lpOut++ = runcount - 1;
  161.         lmemcpy (lpOut, lpIn, runcount);
  162.         lpOut += runcount;
  163.         lpIn += runcount;
  164.     }
  165.     else if (state == UNDECIDED) {
  166.         if (runcount < 1 || runcount > 127) {
  167.             DBMSG(("PackBits: runcount=%d\n",runcount));
  168.             goto cu0;
  169.         }
  170.         /* write out runcount/2 twin replicate runs
  171.          */
  172.         for (twins = (runcount>>1); twins--; ) {
  173.             *lpOut++ = -1;
  174.             *lpOut++ = *lpIn;
  175.             lpIn += 2;
  176.         }
  177.     }
  178.  
  179.     /* set up return values
  180.      */
  181.     *plpIn = lpIn;
  182.     *plpOut = lpOut;
  183.  
  184. cu0: return;
  185.  
  186. } /* that's all, folks */
  187.  
  188. #endif    /* ifndef MACINTOSH */
  189.  
  190. /* if you might have more than 127 input bytes, call this routine instead
  191.  * of the basic PackBits
  192.  */
  193. void BigPackBits ARGS((LPSTR *, LPSTR *, WORD));
  194. LOCAL void BigPackBits (plpIn, plpOut, n)
  195. LPSTR    *plpIn;
  196. LPSTR    *plpOut;
  197. WORD    n;
  198. {
  199.         WORD    topack;
  200.  
  201.         while (n) {
  202.             topack = (n < MAXINBYTES) ? n : MAXINBYTES;
  203.             PackBits (plpIn, plpOut, topack);
  204.             n -= topack;
  205.         }
  206. }
  207.